package com.ling.core.common.utils;

import com.bstek.dorado.data.entity.EntityState;
import com.bstek.dorado.data.entity.EntityUtils;
import com.bstek.dorado.data.entity.FilterType;
import com.bstek.dorado.data.provider.*;
import com.bstek.dorado.data.provider.Junction;
import com.bstek.dorado.data.provider.filter.FilterOperator;
import com.bstek.dorado.data.provider.filter.SingleValueFilterCriterion;
import com.ling.pl.core.commons.enums.DataStatus;
import com.ling.pl.core.commons.support.DaoPage;
import com.ling.pl.core.commons.utils.PageUtils;
import org.apache.commons.lang.StringUtils;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.*;

import java.util.*;


public class D7PageUtils {
    public static DetachedCriteria buildDetachedCriteria(Criteria criteria, Class<?> entityClass) {
        return buildDetachedCriteria(criteria, entityClass, null);
    }

    public static DetachedCriteria buildDetachedCriteria(Criteria criteria, Class<?> entityClass, String alias) {
        DetachedCriteria dc = null;
        if (StringUtils.isEmpty(alias)) {
            dc = DetachedCriteria.forClass(entityClass);
        } else {
            dc = DetachedCriteria.forClass(entityClass, alias);
        }
        if (criteria != null && criteria.getCriterions().size() > 0) {
            buildCriterions(criteria.getCriterions(), dc);
        }
        return dc;
    }

    public static Map buildQueryParams(Criteria criteria) {
        return buildQueryParams(criteria, null);
    }

    public static Map buildQueryParams(Criteria criteria, Page page) {
        Map<String, Object> params = new HashMap<String, Object>();
        if (criteria != null) {
            for (com.bstek.dorado.data.provider.Criterion criterion : criteria.getCriterions()) {
                SingleValueFilterCriterion fc = (SingleValueFilterCriterion) criterion;
                params.put(fc.getProperty(), fc.getValue());
            }
        }
        if (page != null) {
            params.put(PageUtils.pageIndex, page.getPageNo());
            params.put(PageUtils.pageNumber, page.getPageSize());
        }
        return params;

    }

    public static Map buildQueryParams(Map params, Page page) {
        if (params == null) {
            params = new HashMap<String, Object>();
        }
        if (page != null) {
            params.put(PageUtils.pageIndex, page.getPageNo());
            params.put(PageUtils.pageNumber, page.getPageSize());
        }
        return params;

    }

    private static void buildCriterions(Collection<com.bstek.dorado.data.provider.Criterion> criterions, DetachedCriteria dc) {
        for (com.bstek.dorado.data.provider.Criterion c : criterions) {
            if (c instanceof SingleValueFilterCriterion) {
                SingleValueFilterCriterion fc = (SingleValueFilterCriterion) c;
                dc.add(buildCriterion(fc));
            }
            if (c instanceof Junction) {
                Junction jun = (Junction) c;
                if (jun instanceof Or) {
                    dc.add(Restrictions.disjunction());
                } else if (jun instanceof And) {
                    dc.add(Restrictions.conjunction());
                }
                Collection<com.bstek.dorado.data.provider.Criterion> subCriterions = jun.getCriterions();
                if (subCriterions != null) {
                    buildCriterions(subCriterions, dc);
                }
            }
        }
    }

    private static Criterion buildCriterion(SingleValueFilterCriterion fc) {
        Criterion result = null;
        String operator = buildOperator(fc.getFilterOperator());
        String propertyName = fc.getProperty();
        Property p = Property.forName(propertyName);
        if (operator.equals("like")) {
            result = p.like("%" + fc.getValue() + "%");
        } else if (operator.startsWith("*")) {
            result = p.like((String) fc.getValue(), MatchMode.END);
        } else if (operator.endsWith("*")) {
            result = p.like((String) fc.getValue(), MatchMode.START);
        } else if (operator.equals(">")) {
            result = p.gt(fc.getValue());
        } else if (operator.equals("<")) {
            result = p.lt(fc.getValue());
        } else if (operator.equals(">=")) {
            result = p.ge(fc.getValue());
        } else if (operator.equals("<=")) {
            result = p.le(fc.getValue());
        } else if (operator.equals("=")) {
            result = p.eq(fc.getValue());
        } else if (operator.equals("!=")) {
            result = p.ne(fc.getValue());
        } else {
            throw new IllegalArgumentException("Query operator[" + operator + "] is invalide");
        }
        return result;
    }

    //	private static com.ling2.core.model.provider.Criteria buildCriterion(Criteria doradoCriteria){
//		com.ling2.core.model.provider.Criteria criteria=new com.ling2.core.model.provider.Criteria();
//		for(com.bstek.dorado.data.provider.Criterion c : doradoCriteria.getCriterions()){
//			if (c instanceof SingleValueFilterCriterion){
//				SingleValueFilterCriterion fc = (SingleValueFilterCriterion) c;
//				DefaultCriterion criterion=new DefaultCriterion();
//				criterion.setExpression(fc.getExpression());
//				criterion.setFilterOperator(fc.getFilterOperator());
//				criterion.setProperty(fc.getProperty());
//				criterion.setPropertyPath(fc.getPropertyPath());
//				criterion.setValue(fc.getValue());
//			}
//			if(c instanceof Junction){
//				Junction jun=(Junction)c;
//				if(jun instanceof Or){
//					dc.add(Restrictions.disjunction());
//				}else if(jun instanceof And){
//					dc.add(Restrictions.conjunction());
//				}
//				Collection<com.bstek.dorado.data.provider.Criterion> subCriterions=jun.getCriterions();
//				if(subCriterions!=null){
//					buildCriterions(subCriterions,dc);
//				}
//			}
//		}
//		return criteria;
//	}
//	private static Map buildCriterionMap(Map params,SingleValueFilterCriterion fc){
//		if(params==null){
//			params=new HashMap();
//		}
//		String operator=buildOperator(fc.getFilterOperator());
//		String propertyName=fc.getProperty();
////		Property p=Property.forName(propertyName);
//		if(operator.equals("like")){
//			params.put(propertyName, "%"+fc.getValue()+"%");
//		}else if(operator.startsWith("*")){
//			params.put(propertyName, "%"+fc.getValue());
//		}else if(operator.endsWith("*")){
//			params.put(propertyName, fc.getValue()+"%");
//		}else if(operator.equals(">")){
//			result=p.gt(fc.getValue());
//		}else if(operator.equals("<")){
//			result=p.lt(fc.getValue());
//		}else if(operator.equals(">=")){
//			result=p.ge(fc.getValue());
//		}else if(operator.equals("<=")){
//			result=p.le(fc.getValue());
//		}else if(operator.equals("=")){
//			result=p.eq(fc.getValue());
//		}else if(operator.equals("!=")){
//			result=p.ne(fc.getValue());
//		}else{
//			throw new IllegalArgumentException("Query operator["+operator+"] is invalide");
//		}
//		return result;
//	}
    protected static String buildOperator(FilterOperator filterOperator) {
        String operator = "like";
        if (filterOperator != null) {
            operator = filterOperator.toString();
        }
        return operator;
    }

    public static void daoPageToPage(DaoPage daoPage, Page page) {
        page.setEntities(daoPage.getResult());
        page.setEntityCount(daoPage.getRecordCount());
    }

    public static Map assembleDatasetMap(Collection records) {
        if (records == null) {
            records = new ArrayList();
        }
        Map datasetMap = new HashMap();
        List insertList = new ArrayList();
        List updateList = new ArrayList();
        List deleteList = new ArrayList();
        for (Object record : records) {
            EntityState state = EntityUtils.getState(record);

            if (state.equals(EntityState.NEW)) {
                insertList.add(record);
            }
            if (state.equals(EntityState.MODIFIED) || state.equals(EntityState.MOVED)) {
                updateList.add(record);
            }
            if (state.equals(EntityState.DELETED)) {
                deleteList.add(record);
            }
        }
        datasetMap.put(DataStatus.DELETE, deleteList);
        datasetMap.put(DataStatus.INSERT, insertList);
        datasetMap.put(DataStatus.MODIFIED, updateList);
        return datasetMap;
    }

    public static Collection getInsertEntities(Collection objs) {
        List newlists = new ArrayList();
        for (Iterator iter = EntityUtils.getIterator(objs, FilterType.NEW); iter.hasNext(); ) {
            newlists.add(iter.next());
        }
        return newlists;
    }

    public static Object getFirstInsertEntities(Collection objs) {
        List newlists = new ArrayList();
        for (Iterator iter = EntityUtils.getIterator(objs, FilterType.NEW); iter.hasNext(); ) {
            return iter.next();
        }
        return null;
    }

    public static Collection getModifiedEntities(Collection objs) {
        List modifylists = new ArrayList();
        for (Iterator iter = EntityUtils.getIterator(objs, FilterType.MODIFIED); iter.hasNext(); ) {
            modifylists.add(iter.next());
        }
        return modifylists;
    }

    public static Collection getDeleteEntities(Collection objs) {
        List deletedlists = new ArrayList();
        for (Iterator iter = EntityUtils.getIterator(objs, FilterType.DELETED); iter.hasNext(); ) {
            deletedlists.add(iter.next());
        }
        return deletedlists;
    }

    public static Map preProcessMap(Map params, String namePattern) {
        if (params == null) {
            params = new HashMap();
        }
        params.put("namePattern", namePattern);
        return params;
    }

    /**
     * 子类可以覆盖该方法，以决定该如何根据给出的字段名构建拼装查询条件的字段名
     *
     * @param name 需要重新构建的查询字段名
     * @return 返回构建好的字段名
     */
    protected String buildFieldName(String name) {
        return name;
    }
}
